package br.com.sisgerenciamento.dao.produto;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.AliasToBeanResultTransformer;

import br.com.sisgerenciamento.dto.produto.ProdutoDTO;
import br.com.sisgerenciamento.exceptions.AlterarException;
import br.com.sisgerenciamento.exceptions.ApplicationException;
import br.com.sisgerenciamento.exceptions.ExcluirException;
import br.com.sisgerenciamento.exceptions.InserirException;
import br.com.sisgerenciamento.generic.GenericDAO;
import br.com.sisgerenciamento.model.produto.ProdutoVO;
import br.com.sisgerenciamento.model.produto.TipoProdutoEnum;
import br.com.sisgerenciamento.model.unidade.UnidadeProdutoVO;

public class ProdutoDAOServiceImpl extends GenericDAO< ProdutoVO > implements ProdutoDAOService{

	public ProdutoVO inserir( ProdutoVO vo ) throws InserirException {
		return (ProdutoVO) insert( vo );
	}

	public void alterar( ProdutoVO vo ) throws AlterarException {
		update( vo );
	}

	public void excluir( ProdutoVO vo ) throws ExcluirException {
		delete( vo );
	}

	public ProdutoVO obterProdutoPorCodigo( Long codigo ) throws ApplicationException {
		Session session = getSessionAberta();
		try {
			Criteria criteria = session.createCriteria( ProdutoVO.class );
			criteria.add( Restrictions.eq( "codigo", codigo ) );
			return (ProdutoVO) consultar( criteria );
		} catch ( Exception e ) {
			throw new ApplicationException( e.getMessage() );
		} finally {
			if ( session != null )
				session.close();
		}
	}

	@SuppressWarnings( "unchecked" )
	public List< UnidadeProdutoVO > listarUnidades() throws ApplicationException {
		Session session = null;
		try {
			session = getSessionAberta();
			Query query = session.createQuery( "SELECT u FROM UnidadeProdutoVO u ORDER BY u.descricao " );
			List< UnidadeProdutoVO > list = query.list();
			return list;
		} catch ( Exception e ) {
			throw new HibernateException( e.getMessage() );
		} finally {
			if ( session != null )
				session.close();
		}
	}

	@SuppressWarnings( "unchecked" )
	public List< String > consultarPorDescricao( String descricao ) throws ApplicationException {
		Session session = null;
		try {
			session = getSessionAberta();
			Query query = session.createQuery( "SELECT p.descricao FROM ProdutoVO p where p.descricao like :descricao ORDER BY p.descricao " );
			query.setString( "descricao", "%" + descricao + "%" );
			List< String > list = query.list();
			return list;
		} catch ( Exception e ) {
			throw new HibernateException( e.getMessage() );
		} finally {
			if ( session != null )
				session.close();
		}
	}

	@SuppressWarnings( "unchecked" )
	public List< ProdutoVO > consultarProdutoPorDescricao( String descricao ) throws ApplicationException {
		Session session = null;
		try {
			session = getSessionAberta();
			Query query = session.createQuery( "SELECT p FROM ProdutoVO p where p.descricao like :descricao ORDER BY p.descricao " );
			query.setString( "descricao", "%" + descricao + "%" );
			List< ProdutoVO > list = query.list();
			return list;
		} catch ( Exception e ) {
			throw new HibernateException( e.getMessage() );
		} finally {
			if ( session != null )
				session.close();
		}
	}

	@SuppressWarnings( "unchecked" )
	public ArrayList< ProdutoVO > listarAtivos() throws ApplicationException {
		Session session = null;
		try {
			session = getSessionAberta();
			Query query = session.createQuery( "SELECT p FROM ProdutoVO p where p.status = :status ORDER BY p.descricao " );
			query.setBoolean( "status", new Boolean( true ) );
			return (ArrayList< ProdutoVO >) query.list();
		} catch ( Exception e ) {
			throw new ApplicationException( e.getMessage() );
		} finally {
			if ( session != null )
				session.close();
		}
	}

	@SuppressWarnings( "unchecked" )
	public ArrayList< ProdutoVO > listar() throws ApplicationException {
		Session session = null;
		try {
			session = getSessionAberta();
			Query query = session.createQuery( "SELECT p FROM ProdutoVO p ORDER BY p.descricao " );
			return (ArrayList< ProdutoVO >) query.list();
		} catch ( Exception e ) {
			throw new ApplicationException( e.getMessage() );
		} finally {
			if ( session != null )
				session.close();
		}
	}

	@SuppressWarnings( "unchecked" )
	public ArrayList< ProdutoDTO > listarProdutosProntaEntrega() throws ApplicationException {
		Session session = null;

		StringBuilder sql = new StringBuilder();
		sql.append( "SELECT prod.codigo AS codigo, " );
		sql.append( "prod.descricao AS descricao, " );
		sql.append( "prod.quantidade AS quantidade " );
		sql.append( "FROM produto prod " );
		sql.append( "WHERE prod.tipo = :tipo  " );
		sql.append( "AND prod.status = :status order by prod.descricao" );
		try {
			session = getSessionAberta();
			SQLQuery sqlQuery = session.createSQLQuery( sql.toString() );
			sqlQuery.addScalar( "codigo", Hibernate.STRING );
			sqlQuery.addScalar( "descricao", Hibernate.STRING );
			sqlQuery.addScalar( "quantidade", Hibernate.STRING );

			sqlQuery.setInteger( "tipo", TipoProdutoEnum.PRONTA_ENTREGA.ordinal() );
			sqlQuery.setBoolean("status", true);
			sqlQuery.setResultTransformer( new AliasToBeanResultTransformer( ProdutoDTO.class ) );
			return (ArrayList< ProdutoDTO >) sqlQuery.list();
		} catch ( Exception e ) {
			throw new ApplicationException( e.getMessage() );
		} finally {
			if ( session != null )
				session.close();
		}
	}

	@SuppressWarnings( "unchecked" )
	public ArrayList< ProdutoDTO > consultarProdutoProntaEntregaPorDescricao( String descricao ) throws ApplicationException {
		Session session = null;

		StringBuilder sql = new StringBuilder();
		sql.append( "SELECT prod.codigo AS codigo, " );
		sql.append( "prod.descricao AS descricao, " );
		sql.append( "prod.quantidade AS quantidade " );
		sql.append( "FROM produto prod " );
		sql.append( "WHERE prod.tipo = :tipo " );
		sql.append( "AND prod.descricao LIKE :descricao " );
		sql.append( "ORDER BY prod.descricao" );

		try {
			session = getSessionAberta();
			SQLQuery sqlQuery = session.createSQLQuery( sql.toString() );
			sqlQuery.addScalar( "codigo", Hibernate.STRING );
			sqlQuery.addScalar( "descricao", Hibernate.STRING );
			sqlQuery.addScalar( "quantidade", Hibernate.STRING );

			sqlQuery.setInteger( "tipo", TipoProdutoEnum.PRONTA_ENTREGA.getValor() );
			sqlQuery.setString( "descricao", "%" + descricao + "%" );

			sqlQuery.setResultTransformer( new AliasToBeanResultTransformer( ProdutoDTO.class ) );
			return (ArrayList< ProdutoDTO >) sqlQuery.list();
		} catch ( Exception e ) {
			throw new ApplicationException( e.getMessage() );
		} finally {
			if ( session != null )
				session.close();
		}
	}

}
